package com.chinawayltd.ews.sample.service.task.impl;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.chinawayltd.ews.sample.core.exception.BusinessException;
import com.chinawayltd.ews.sample.mapper.TBranchMapper;
import com.chinawayltd.ews.sample.mapper.TDriverMapper;
import com.chinawayltd.ews.sample.mapper.TLogMapper;
import com.chinawayltd.ews.sample.mapper.TNodeOrderMapper;
import com.chinawayltd.ews.sample.mapper.TOrderDetailMapper;
import com.chinawayltd.ews.sample.mapper.TTaskMapper;
import com.chinawayltd.ews.sample.mapper.TTaskNodeExtendMapper;
import com.chinawayltd.ews.sample.mapper.TTaskNodeMapper;
import com.chinawayltd.ews.sample.mapper.TTaskOrderMapper;
import com.chinawayltd.ews.sample.mapper.TVehicleCustomMapper;
import com.chinawayltd.ews.sample.mapper.TVehicleMapper;
import com.chinawayltd.ews.sample.mapper.order.OrderExtendMapper;
import com.chinawayltd.ews.sample.mapper.task.TaskExtendMapper;
import com.chinawayltd.ews.sample.mapper.task.TaskNodeExtendMapper;
import com.chinawayltd.ews.sample.model.TBranch;
import com.chinawayltd.ews.sample.model.TDriver;
import com.chinawayltd.ews.sample.model.TLog;
import com.chinawayltd.ews.sample.model.TMateriel;
import com.chinawayltd.ews.sample.model.TNodeOrderKey;
import com.chinawayltd.ews.sample.model.TOrderDetailExample;
import com.chinawayltd.ews.sample.model.TTask;
import com.chinawayltd.ews.sample.model.TTaskNode;
import com.chinawayltd.ews.sample.model.TTaskNodeExtend;
import com.chinawayltd.ews.sample.model.TTaskOrder;
import com.chinawayltd.ews.sample.model.TTemplateNode;
import com.chinawayltd.ews.sample.model.TVehicle;
import com.chinawayltd.ews.sample.model.TVehicleCustom;
import com.chinawayltd.ews.sample.model.algorithm.DriverTaskVO;
import com.chinawayltd.ews.sample.model.algorithm.DriverWorkVO;
import com.chinawayltd.ews.sample.model.order.OrderDetailVO;
import com.chinawayltd.ews.sample.model.order.OrderVO;
import com.chinawayltd.ews.sample.model.task.TaskBranchVO;
import com.chinawayltd.ews.sample.model.task.TaskListVO;
import com.chinawayltd.ews.sample.model.task.TaskOrderDetailVO;
import com.chinawayltd.ews.sample.model.task.TaskScreenVO;
import com.chinawayltd.ews.sample.model.task.TaskStockVO;
import com.chinawayltd.ews.sample.model.task.TaskVO;
import com.chinawayltd.ews.sample.service.base.impl.BaseServiceImpl;
import com.chinawayltd.ews.sample.service.task.TaskService;
import com.chinawayltd.ews.sample.util.ResultModel;
import com.chinawayltd.ews.sample.util.StringUtils;
import com.chinawayltd.ews.sample.utils.TaskDispathDateUtils;
import com.chinawayltd.ews.sample.web.query.AppGirdQuery;
import com.chinawayltd.ews.sample.web.query.DriverGirdQuery;
import com.chinawayltd.ews.sample.web.query.OrderDetailGirdQuery;
import com.chinawayltd.ews.sample.web.query.TaskGirdQuery;

/**
 * @program: greeProject
 * @description 运输任务管理service
 * @author: chenxin
 * @create: 2018年4月16日 下午5:13:49
 */
@Service
public class TaskServiceImpl extends BaseServiceImpl implements TaskService {
	private static final SimpleDateFormat HHMM = new SimpleDateFormat("HH:mm");
	@Autowired
	private TaskExtendMapper taskExtendMapper;
	@Autowired
	private TTaskMapper tTaskMapper;
	@Autowired
	private TaskNodeExtendMapper taskNodeExtendMapper;
	@Autowired
	private TTaskOrderMapper tTaskOrderMapper;
    @Autowired
    private TDriverMapper tDriverMapper;
    @Autowired
    private TVehicleMapper tVehicleMapper;
    @Autowired
    private TOrderDetailMapper tOrderDetailMapper;
    @Autowired
    private OrderExtendMapper orderExtendMapper;
    @Autowired
    private TLogMapper tLogMapper;
	@Autowired
	private TTaskNodeMapper tTaskNodeMapper;
	@Autowired
	private TTaskNodeExtendMapper tTaskNodeExtendMapper;
	@Autowired
	private TNodeOrderMapper tNodeOrderMapper;
	@Autowired
	private TVehicleCustomMapper tVehicleCustomMapper;
	@Autowired
	private TBranchMapper tBranchMapper;

    private final String tableNameTask = "T_TASK";
    
    private static final SimpleDateFormat YYYYMMDD_HHMMSS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	@Override
	public List<TaskListVO> listTaskAndOrderByPage(TaskGirdQuery queryParam) throws Exception {
    	if(StringUtils.isBlank(queryParam.getSortStr())){
    		queryParam.setSort(0);
    		queryParam.setSortStr("confirm_state, start_time");
    	}
		return taskExtendMapper.listTaskAndOrderByPage(queryParam);
	}

	@Override
	public TTask getTaskById(Long id) throws Exception {
		// 判断id是否为空
    	if(id == null || id <= 0){
            throw new RuntimeException("id不能为空或者少于等于0！");
        }
		return tTaskMapper.selectByPrimaryKey(id);
	}
	
	@Override
	@Transactional
	public void insertTask(TaskOrderDetailVO taskOrderDetailVO) throws Exception {
		Date date = new Date();
		//1.新增任务信息
		TTask task = new TTask();
		task.setTaskNo("U" + StringUtils.DateToStr(date, "yyyyMMddHHmmss"));//任务编号
		TVehicle vehicle = tVehicleMapper.selectByPrimaryKey(taskOrderDetailVO.getVehicleId());
		if(vehicle == null) throw new BusinessException("车牌号不存在，添加失败!");
		task.setVehicleNumber(vehicle.getCarNum());
		task.setVehicleId(taskOrderDetailVO.getVehicleId());
		
		TDriver driver = tDriverMapper.selectByPrimaryKey(taskOrderDetailVO.getDriverId());
		if(driver == null) throw new BusinessException("司机不存在，添加失败!");
		task.setDriverName(driver.getDriverName());
		task.setDriverId(taskOrderDetailVO.getDriverId());
		String startTimeStr = taskOrderDetailVO.getStartTimeStr();
		if(org.apache.commons.lang3.StringUtils.isNoneBlank(startTimeStr)){
			task.setStartTime(YYYYMMDD_HHMMSS.parse(startTimeStr));
		}
		String finishTimeStr = taskOrderDetailVO.getFinishTimeStr();
		if(org.apache.commons.lang3.StringUtils.isNoneBlank(finishTimeStr)){
			task.setFinishTime(YYYYMMDD_HHMMSS.parse(finishTimeStr));
		}
		
		if(YYYYMMDD_HHMMSS.parse(startTimeStr).getTime() >= YYYYMMDD_HHMMSS.parse(finishTimeStr).getTime()){
			throw new BusinessException("计划开始时间不能大于等于计划完成时间！");
		}
		
		//判断板位总数是否符合车辆板位数
		boolean flag = this.judgeTransportUnit(taskOrderDetailVO);
		if(!flag) throw new BusinessException("由于车辆规定的板位数小于订单总板位数，添加失败!");
		task.setConfirmState((byte)0);
		task.setExecutState((byte)0);
		task.setCreateTime(date);
		task.setUpdateTime(date);
		TVehicleCustom vehicleCustom = tVehicleCustomMapper.selectByPrimaryKey(task.getVehicleId());
		if(vehicleCustom.getCarvldTime() !=null){
			if(task.getFinishTime().getTime() > vehicleCustom.getCarvldTime().getTime()){
				vehicleCustom.setCarvldTime(task.getFinishTime());
				tVehicleCustomMapper.updateByPrimaryKeySelective(vehicleCustom);
			}
		}else{
			vehicleCustom.setCarvldTime(task.getFinishTime());
			tVehicleCustomMapper.updateByPrimaryKeySelective(vehicleCustom);
		}
		// 1新增任务
		taskExtendMapper.insert(task);
		Long taskId = task.getId();//得到任务id
		// 2生成任务节点
		generateTaskNodeData(taskOrderDetailVO, taskId);
		// 3获取订单详细来新增订单信息和修改任务板位数
		insertTaskOrder(taskOrderDetailVO.getDetailList(), taskId);
		// 4更新当前运输任务所关联的订单的生成状态,将与任务关联的订单生成状态改为已生成(已调度)
		updateOrderGenerateStatus(taskId, 2, date);
		// 5增加日记
		insertLog(taskId, 1, date);
	}
	/**
	 * 修改任务关联的订单的调度状态，0为未调度1为调度中2已调度
	 * @author: chenxin
	 * @date: 2018年6月22日 上午9:43:50
	 * @param taskId
	 * @param i 
	 * @param date
	 */
	private void updateOrderGenerateStatus(Long taskId, int i, Date date) {
		Map<String, Object> map = new HashMap<>();
		map.put("statusNum", i);
		map.put("taskId", taskId);
		map.put("updateTime", date);
		orderExtendMapper.updateOrderGenerateStatus(map);
	}
	/**
	 * 保存任务操作日志
	 * @author: chenxin
	 * @date: 2018年6月22日 上午9:45:21
	 * @param taskId
	 * @param i 
	 * @param date
	 */
	private void insertLog(Long taskId, int i, Date date) {
		TLog log = new TLog();
		log.setDataId(taskId);
		log.setTableName(tableNameTask);
		log.setOperationUser(getCurrentUser().getRealname());
		log.setOperationType(i);
		log.setCreateTime(date);
		log.setUpdateTime(date);
		tLogMapper.insertSelective(log);
	}
	/**
	 * 保存新增任务所关联的订单及订单明细、修改任务板位数
	 * @author: chenxin
	 * @date: 2018年6月22日 上午9:43:47
	 * @param detailList
	 * @param taskId 
	 */
	private void insertTaskOrder(List<OrderVO> detailList, Long taskId) throws Exception {
		Date date = new Date();
		BigDecimal totalPallet = new BigDecimal(0);
		if(detailList != null && detailList.size() > 0){
			for(OrderVO detailVo : detailList){
				Long orderId = detailVo.getId();
				//3-1添加t_task_order中间表
				TTaskOrder tTaskOrder = new TTaskOrder();
				tTaskOrder.setOrderId(orderId);
				tTaskOrder.setTaskId(taskId);
				int insertTaskOrder = tTaskOrderMapper.insert(tTaskOrder);
				if(insertTaskOrder > 0){
					//3-2先将有关于这个id的订单详细删除，再新增
					TOrderDetailExample example = new TOrderDetailExample();
					example.createCriteria().andOrderIdEqualTo(orderId);
					tOrderDetailMapper.deleteByExample(example);
					//3-3删除后再新增
					List<OrderDetailVO> orderDetailList = detailVo.getOrderDetailList();
					if(orderDetailList != null && orderDetailList.size() > 0){
						for(OrderDetailVO orderDetailVO : orderDetailList){
							orderDetailVO.setCreateTime(date);
							orderDetailVO.setUpdateTime(date);
							if(orderDetailVO.getPlanNumber() ==null || orderDetailVO.getPlanNumber() <=0) throw new BusinessException("订单存在物料数量小于等于0");
							if(orderDetailVO.getTransportBoard() ==null) throw new BusinessException("订单板位数不能小于等于0");
							BigDecimal bigDecimal = new BigDecimal(0);
							if(orderDetailVO.getTransportBoard().compareTo(bigDecimal) <=0) throw new BusinessException("订单板位数不能小于等于0");
							orderDetailVO.setOrderId(orderId);
							orderDetailVO.setId(null);
							tOrderDetailMapper.insertSelective(orderDetailVO);
							totalPallet = totalPallet.add(orderDetailVO.getTransportBoard());
						}
					}else{
						throw new BusinessException("任务中的订单至少有一个物料明细!");
					}
				}else{
					throw new BusinessException("任务添加订单失败!");
				}
			}
		}else{
			throw new BusinessException("任务至少有一个订单信息!");
		}
		//修改任务的板位数
		TTask task = new TTask();
		task.setId(taskId);
		task.setRoutPallet(totalPallet);
		updateTaskRoutPallet(task);
	}

	/**判断板位总数是否符合车辆板位数
	 * @author Fay
	 * @date 2018年5月28日 下午4:31:09
	 * @param taskOrderDetailVO
	 * @return
	 */
	private boolean judgeTransportUnit(TaskOrderDetailVO taskOrderDetailVO) {
		List<OrderVO> detailList = taskOrderDetailVO.getDetailList();
		BigDecimal totalTransportUnit = new BigDecimal(0);
		for(OrderVO orderVO : detailList){
			BigDecimal transportUnit = orderVO.getTransportUnit() != null ? orderVO.getTransportUnit() : new BigDecimal(0);
			totalTransportUnit = totalTransportUnit.add(transportUnit);
		}
		
		TVehicleCustom vehicle = tVehicleCustomMapper.selectByPrimaryKey(taskOrderDetailVO.getVehicleId());
		Byte carVolume = vehicle.getCarVolume() != null ? vehicle.getCarVolume() : 30;
		BigDecimal carVolumeBigDecimal = new BigDecimal(carVolume);
		if(carVolumeBigDecimal.compareTo(totalTransportUnit) < 0){//如果车辆板位数小于总板位数，则不符合
			return false;
		}
		return true;
	}

	/**
	 * 生成任务节点信息
	 * @param taskOrderDetailVO
	 * @param taskId
	 */
	private void generateTaskNodeData(TaskOrderDetailVO taskOrderDetailVO, Long taskId) {
		//根据车辆id找到对应的任务模板信息
		Long vehicleId = taskOrderDetailVO.getVehicleId();
		List<TTemplateNode> templateNodes = taskExtendMapper.selectTaskTemplateByVehicleId(vehicleId);
		byte nodeNo = 1;
		//生成任务节点
		for (TTemplateNode templateNode : templateNodes) {
			Byte nodeType = templateNode.getNodeType();
			if(nodeType == 21) {//卸货节点
				nodeNo += insertUnLoadingNode(taskOrderDetailVO, taskId, nodeNo, templateNode);
			}else if(nodeType == 20){//装货节点
				nodeNo += insertLoadingNode(taskOrderDetailVO, taskId, nodeNo, templateNode);
			}else{//其他通用节点
				TTaskNode taskNode = initTaskNode(templateNode, taskId, nodeNo);//构建对象
				Date estimateFinishTime = null;
				if(nodeType == 0){//任务开始节点的预计完成时间
					estimateFinishTime = taskOrderDetailVO.getStartTime();
				}else if(nodeType == 1){//任务结束节点的预计完成时间
					estimateFinishTime = taskOrderDetailVO.getFinishTime();
				}
				taskNode.setEstimateFinishTime(estimateFinishTime);
				tTaskNodeMapper.insert(taskNode);
				nodeNo++;
			}
		}

	}

	/**
	 * 保存装货自定义扩展表内容与对应得订单关系
	 * @param taskOrderDetailVO
	 * @param taskId
	 * @param nodeNo
	 * @param templateNode
	 * @return
	 */
	private byte insertLoadingNode(TaskOrderDetailVO taskOrderDetailVO, Long taskId, byte nodeNo, TTemplateNode templateNode) {
		List<OrderVO> detailList = taskOrderDetailVO.getDetailList();
		//把当前任务所有订单排序，根据最早送货时间排正序
		detailList.sort((OrderVO o1, OrderVO o2) ->{
			Date time1 = o1.getEarlyDeliveryTime();
			Date time2 = o2.getEarlyDeliveryTime();
			if(time1 != null && time2 != null){
				return time1.compareTo(time2);
			}
			return 0;
		});

		Long lastPickupId = null;
		Set<Long> orderIds = new HashSet<>();
		byte nodeLen = 0;
		for (OrderVO order : detailList) {
			Long pickupId = order.getStartPlaceId();
			if(lastPickupId == null || lastPickupId == pickupId){
				lastPickupId = pickupId;
				orderIds.add(order.getId());
			}else{
				insertExtendNodeToDB(templateNode, taskId, nodeNo, lastPickupId, orderIds, nodeLen);
				nodeLen++;
				lastPickupId = pickupId;
				orderIds.clear();
				orderIds.add(order.getId());
			}
		}
		insertExtendNodeToDB(templateNode, taskId, nodeNo, lastPickupId, orderIds, nodeLen);
		nodeLen++;
		return nodeLen;
	}

	/**
	 * 保存卸货自定义扩展表内容与对应得订单关系
	 * @param taskOrderDetailVO
	 * @param taskId
	 * @param nodeNo
	 * @param templateNode
	 * @return
	 */
	private byte insertUnLoadingNode(TaskOrderDetailVO taskOrderDetailVO, Long taskId, byte nodeNo, TTemplateNode templateNode) {
		List<OrderVO> detailList = taskOrderDetailVO.getDetailList();
		//把当前任务所有订单排序，根据最晚送货时间排正序
		detailList.sort((OrderVO o1, OrderVO o2) ->{
			Date time1 = o1.getLastDeliveryTime();
			Date time2 = o2.getLastDeliveryTime();
			if(time1 != null && time2 != null){
				return time1.compareTo(time2);
			}
			return 0;
		});

		//根据当前任务的订单整合装货节点对应的卸货订单信息
		Long lastDeliveryId = null;
		Set<Long> orderIds = new HashSet<>();
		byte nodeLen = 0;
		for (OrderVO order : detailList) {
			Long deliveryId = order.getEndPlaceId();
			if(lastDeliveryId == null || lastDeliveryId == deliveryId){
				lastDeliveryId = deliveryId;
				orderIds.add(order.getId());
			}else{
				insertExtendNodeToDB(templateNode, taskId, nodeNo, lastDeliveryId, orderIds, nodeLen);
				nodeLen++;
				lastDeliveryId = deliveryId;
				orderIds.clear();
				orderIds.add(order.getId());
			}
		}
		insertExtendNodeToDB(templateNode, taskId, nodeNo, lastDeliveryId, orderIds, nodeLen);
		nodeLen++;

		return nodeLen;
	}

	private void insertExtendNodeToDB(TTemplateNode templateNode, Long taskId, byte nodeNo, Long branchId, Set<Long> orderIds, byte nodeLen) {
		Date date = new Date();
		TBranch branch = tBranchMapper.selectByPrimaryKey(branchId);
		String branchName = branch.getBranchName();
		//新增节点信息
		TTaskNode node = initTaskNode(templateNode, taskId, (byte) (nodeNo + nodeLen));
		node.setNodeName(node.getNodeName() + "(" + branchName + ")");
		tTaskNodeMapper.insert(node);

		//新增装卸货扩展表信息
		TTaskNodeExtend nodeEx = new TTaskNodeExtend();
		nodeEx.setId(node.getId());
		nodeEx.setBranchId(branchId);
		nodeEx.setCreateTime(date);
		nodeEx.setUpdateTime(date);
		tTaskNodeExtendMapper.insert(nodeEx);

		orderIds.forEach(orderId -> {
			//新增装卸货扩展表与订单表关联信息
			TNodeOrderKey nodeOrder = new TNodeOrderKey();
			nodeOrder.setOrderId(orderId);
			nodeOrder.setNodeId(node.getId());
			tNodeOrderMapper.insert(nodeOrder);
		});
	}

	private TTaskNode initTaskNode(TTemplateNode templateNode, Long taskId, byte nodeNo) {
		Date now = new Date();
		TTaskNode result = new TTaskNode();
		result.setTaskId(taskId);
		result.setNodeNo(nodeNo);
		result.setNodeType(templateNode.getNodeType());
		result.setNodeName(templateNode.getNodeName());
		result.setExecutState((byte)0);
		result.setCreateTime(now);
		result.setUpdateTime(now);
		return result;
	}

	@Override
	@Transactional
	public void updateTaskAndOrder(TaskOrderDetailVO taskOrderDetailVO) throws Exception {
		Date date = new Date();
		TTask task = tTaskMapper.selectByPrimaryKey(taskOrderDetailVO.getId());
		TVehicle vehicle = tVehicleMapper.selectByPrimaryKey(taskOrderDetailVO.getVehicleId());
		if(vehicle == null) throw new BusinessException("车牌号不存在，修改失败!");
		task.setVehicleId(taskOrderDetailVO.getVehicleId());
		task.setVehicleNumber(vehicle.getCarNum());
		
		TDriver driver = tDriverMapper.selectByPrimaryKey(taskOrderDetailVO.getDriverId());
		if(driver == null) throw new BusinessException("司机不存在，修改失败!");
		task.setDriverId(taskOrderDetailVO.getDriverId());
		task.setDriverName(driver.getDriverName());
		String startTimeStr = taskOrderDetailVO.getStartTimeStr();
		if(org.apache.commons.lang3.StringUtils.isNoneBlank(startTimeStr)){
			task.setStartTime(YYYYMMDD_HHMMSS.parse(startTimeStr));
		}
		String finishTimeStr = taskOrderDetailVO.getFinishTimeStr();
		if(org.apache.commons.lang3.StringUtils.isNoneBlank(finishTimeStr)){
			task.setFinishTime(YYYYMMDD_HHMMSS.parse(finishTimeStr));
		}
		
		if(YYYYMMDD_HHMMSS.parse(startTimeStr).getTime() > YYYYMMDD_HHMMSS.parse(finishTimeStr).getTime()){
			throw new BusinessException("计划开始时间不能大于计划完成时间！");
		}
		
		task.setUpdateTime(date);
		//判断板位总数是否符合车辆板位数
		boolean flag = this.judgeTransportUnit(taskOrderDetailVO);
		if(!flag) throw new BusinessException("由于车辆规定的板位数小于订单总板位数，修改失败!");
		//1更新任务
		tTaskMapper.updateByPrimaryKeySelective(task);
		//2更新订单和任务板位数
		updateTaskOrder(taskOrderDetailVO.getDetailList(), taskOrderDetailVO.getId());
		//3增加日记
		insertLog(task.getId(), 2, date);
	}
	
	@Override
	@Transactional
	public void updateTaskOrder(TaskOrderDetailVO taskOrderDetailVO) throws Exception {
		//判断板位总数是否符合车辆板位数
		boolean flag = this.judgeTransportUnit(taskOrderDetailVO);
		if(!flag) throw new BusinessException("车辆规定的板位数小于订单总板位数，修改失败!");
		updateTaskOrder(taskOrderDetailVO.getDetailList(), taskOrderDetailVO.getId());
		insertLog(taskOrderDetailVO.getId(), 2, new Date());
	}

	private void updateTaskOrder(List<OrderVO> detailList, Long taskId) throws Exception {
		Date date = new Date();
		BigDecimal totalPallet = new BigDecimal(0);
		if(detailList != null && detailList.size() > 0){
			for(OrderVO detailVo : detailList){
				Byte executeStatus = detailVo.getExecuteStatus();
				Long id = detailVo.getId();
				if(executeStatus == 0 ){// 订单状态为未执行，可修改，略
    				// 删除明细再新增
    				List<OrderDetailVO> orderDetailList = detailVo.getOrderDetailList();
    				if(orderDetailList != null && orderDetailList.size() > 0){
    					// 这个id的订单明细删除，再新增
        				TOrderDetailExample example = new TOrderDetailExample();
        				example.createCriteria().andOrderIdEqualTo(id);
        				tOrderDetailMapper.deleteByExample(example);
        				
    					for(OrderDetailVO orderDetailVO : orderDetailList){
    						orderDetailVO.setCreateTime(date);
    						orderDetailVO.setUpdateTime(date);
    						if(orderDetailVO.getPlanNumber() ==null || orderDetailVO.getPlanNumber() <=0) throw new BusinessException("订单存在物料数量小于等于0");
							if(orderDetailVO.getTransportBoard() ==null) throw new BusinessException("订单板位数不能小于等于0");
							BigDecimal bigDecimal = new BigDecimal(0);
							if(orderDetailVO.getTransportBoard().compareTo(bigDecimal) <=0) throw new BusinessException("订单板位数不能小于等于0");
    						orderDetailVO.setId(null);
    						orderDetailVO.setOrderId(id);
    						tOrderDetailMapper.insertSelective(orderDetailVO);
    						totalPallet = totalPallet.add(orderDetailVO.getTransportBoard());
    					}
    				}else{
    					throw new BusinessException("任务中的订单至少有一个物料明细!");
    				}
				}
			}
		}else{
			throw new BusinessException("任务至少有一个订单信息!");
		}
		//修改任务的板位数
		TTask task = new TTask();
		task.setId(taskId);
		task.setRoutPallet(totalPallet);
		updateTaskRoutPallet(task);
	}

	@Override
	public List<TMateriel> listMaterielNoIds(String ids) throws Exception {
		if(StringUtils.isBlank(ids)){
            throw new RuntimeException("数据不能为空！");
        }
		String[] idArr = ids.split(",");
		return taskExtendMapper.listMaterielNoIds(idArr);
	}

	@Override
	public List<TaskStockVO> listTaskAndOrderDetailByPage(TaskGirdQuery queryParam) throws Exception {
		String sortStr = queryParam.getSortStr().trim();
		if(StringUtils.isNotBlank(sortStr)){
			if(sortStr.contains("ostartPlace")){
				sortStr = sortStr.replaceAll("ostart", "oStart");
			}else if(sortStr.contains("tupdate")){
				sortStr = sortStr.replaceAll("tupdate", "tUpdate");
			}else if(sortStr.contains("tconfirm")){
				sortStr = sortStr.replaceAll("tconfirm", "tConfirm");
			}else if(sortStr.contains("tconfirm")){
				sortStr = sortStr.replaceAll("tconfirm", "tConfirm");
			}else if(sortStr.contains("texecutState")){
				sortStr = sortStr.replaceAll("texecutState", "tExecutState");
			}else if(sortStr.contains("tcreateTime")){
				sortStr = sortStr.replaceAll("tcreateTime", "tCreateTime");
			}
		}else{
			queryParam.setSort(0);
			sortStr = "t_update_time_str, task_no, same_pallet, materiel_no";
		}
		queryParam.setSortStr(sortStr);
		return taskExtendMapper.listTaskAndOrderDetailByPage(queryParam);
	}

	@Override
	public int deleteTaskAndOrderByTaskId(Long id) throws Exception {
		// 判断id是否为空
		if (id == null || id <= 0) {
			throw new RuntimeException("id不能为空或者少于等于0！");
		}
		return taskExtendMapper.deleteTaskAndOrderByTaskId(id);
	}

	@Override
	public int updateNoConfirmStatusByPhone(String phone, Date date) throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("updateTime", date);
		map.put("phone", phone);
		return taskExtendMapper.updateNoConfirmStatusByPhone(map);
	}

	@Override
	@Transactional
	public int deletesByIds(String[] idArr) throws Exception {
		int result = 0;
		for (String string : idArr) {
			result  = 0;
			// 判断运输任务的确认状态：0未确认则可以删除1已确认则不可以删除
			long id = Long.parseLong(string);
        	TTask data = tTaskMapper.selectByPrimaryKey(id);
        	if(data != null ){
        		if(data.getConfirmState() != null && data.getConfirmState() != 0){
        			return 2;//状态不是为未确认
        		}
        		// 删除任务与订单关联
            	result = taskExtendMapper.deleteTaskAndOrderByTaskId(id);
        		//删除任务与订单的关联
            	result = taskNodeExtendMapper.deleteNoteByTaskId(id);
            	result = taskExtendMapper.deleteTask(id);
        		if(result > 0){
        			TLog log = new TLog();
        			log.setCreateTime(new Date());
        			log.setUpdateTime(new Date());
        			log.setDataId(id);
        			log.setTableName(tableNameTask);
        			log.setOperationUser(getCurrentUser().getRealname());
        			log.setOperationType(3);
        			tLogMapper.insertSelective(log);// 增加日记
        		}else{
        			return 0;
        		}
        	}
        	
		}
		return result;
	}

	@Override
	public List<Map<String, Object>> listTaskOrderExportByPage(TaskGirdQuery queryParam) throws Exception {
		return taskExtendMapper.listTaskOrderExportByPage(queryParam);
	}

	@Override
	public List<TaskBranchVO> getTaskBranchList(Long taskId) throws Exception {
		return taskExtendMapper.getTaskBranchList(taskId);
	}

	@Override
	public TaskVO getTaskVOByTaskId(Long taskId) throws Exception {
		// 判断id是否为空
    	if(taskId == null || taskId <= 0){
            throw new RuntimeException("id不能为空或者少于等于0！");
        }
		return taskExtendMapper.getTaskVOByTaskId(taskId);
	}

	@Override
	public List<TaskListVO> applistTaskByPage(AppGirdQuery queryParam) throws Exception {
		List<TaskListVO> list = taskExtendMapper.applistTaskByPage(queryParam);
		return list;
	}
	@Override
	public List<TaskListVO> applistCompleteTaskByPage(AppGirdQuery queryParam) throws Exception {
		return taskExtendMapper.applistCompleteTaskByPage(queryParam);
	}
	
	@Override
	public List<Map<String, Object>> listOrderDetailByTaskId(Long taskId) throws Exception {
		if(taskId == null || taskId <= 0){
            throw new RuntimeException("id不能为空或者少于等于0！");
        }
		return taskExtendMapper.listOrderDetailByTaskId(taskId);
	}
	
	@Override
	public List<Map<String, Object>> listOrderDetailByPage(OrderDetailGirdQuery queryParam) {
		if(queryParam.getTaskId() == null || queryParam.getTaskId() <= 0){
            throw new RuntimeException("数据不能为空或者ID等于0！");
        }
		return taskExtendMapper.listOrderDetailByPage(queryParam);
	}
	
	@Override
	public int updateConfirmStatusByTaskId(Long id, Date date) throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("taskId", id);
		map.put("updateTime", date);
		return taskExtendMapper.updateConfirmStatusByTaskId(map);
	}

	@Override
	public int updateExecutStateByTaskIdAndStatus(Integer statusNum, Long taskId, Date date) throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("statusNum", statusNum);
		map.put("taskId", taskId);
		map.put("updateTime", date);
		return taskExtendMapper.updateExecutStateByTaskIdAndStatus(map);
	}

	@Override
	public int updateOrderGenerateStatusByTaskIdAndStatus(Integer statusNum, Long taskId, Date date) throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("statusNum", statusNum);
		map.put("taskId", taskId);
		map.put("updateTime", date);
		return taskExtendMapper.updateOrderGenerateStatusByTaskIdAndStatus(map);
	}

	@Override
	public int updateOrderExecuteStatusByTaskIdAndStatus(Integer statusNum, Long taskId, Date date) throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("statusNum", statusNum);
		map.put("taskId", taskId);
		map.put("updateTime", date);
		return taskExtendMapper.updateOrderExecuteStatusByTaskIdAndStatus(map);
	}

	@Override
	public int confirmTaskBytaskId(Long taskId) throws Exception {
		// 判断id是否为空
    	if(taskId == null || taskId <= 0){
            throw new RuntimeException("id不能为空或者少于等于0！");
        }
		TTask task = tTaskMapper.selectByPrimaryKey(taskId);
		if(task.getConfirmState() ==1){
			throw new BusinessException("此任务已确认，无需再次确认!");
		}
		Date date = new Date();
		//订单生存状态为生产中
		int result = this.updateOrderGenerateStatusByTaskIdAndStatus(1, taskId, date);
		if(result >0){
			//任务确认
			result = this.updateConfirmStatusByTaskId(taskId, date);
			if(result <=0){
				throw new BusinessException("任务确认失败!");
			}
		}else{
			throw new BusinessException("任务确认失败!");
		}
		return result;
	}

	@Override
	public ResultModel startTaskBytaskId(Long taskId) throws Exception {
		TTask task = tTaskMapper.selectByPrimaryKey(taskId);
		if(task.getConfirmState() !=1){
			return new ResultModel(0, 0, new JSONObject().fluentPut("result" , "任务未确认，请先确认"));
		}
		if(task.getExecutState() >0){
			return new ResultModel(0, 0, new JSONObject().fluentPut("result" , "任务已经开始！"));
		}
		Date date = new Date();
		//订单生存状态为生产中
		//int result = this.updateOrderGenerateStatusByTaskIdAndStatus(1, taskId, date);
		//订单执行中
		int result = this.updateOrderExecuteStatusByTaskIdAndStatus(1, taskId, date);
		if(result >0){
			//任务执行中
			result = this.updateExecutStateByTaskIdAndStatus(1, taskId, date);
			if(result >0)
				return new ResultModel(0, 0, new JSONObject().fluentPut("result" , "开始任务成功"));
			else
				return new ResultModel(0, 1, new JSONObject().fluentPut("sub_msg" , "开始任务失败"));
		}else{
			return new ResultModel(0, 1, new JSONObject().fluentPut("sub_msg" , "开始任务失败"));
		}
	}

	@Override
	public TTask getTaskDetailByTaskId(Long taskId) throws Exception {
		// 根据运输任务id获取运输任务详情
		return tTaskMapper.selectByPrimaryKey(taskId);
	}

	@Override
	public TaskOrderDetailVO selectAllOrderDetailAndSelectedOrder(Long taskId) throws Exception {
		//taskId不能为空
		if(taskId == null || taskId <= 0){
            throw new RuntimeException("id不能为空或者少于等于0！");
        }
		//根据id先查出运输任务信息
		TaskOrderDetailVO taskOrderDetailVO = taskExtendMapper.selectTaskVOByPrimaryKey(taskId);
		if(taskOrderDetailVO != null){
			//根据taskid查询订单信息
			List<OrderVO> orderList = orderExtendMapper.selectOrderVoByTaskId(taskId);
			if(orderList != null && orderList.size() > 0){
				for(OrderVO orderVO : orderList){
					//查询物料信息
					List<OrderDetailVO> OrderDetailVOList = orderExtendMapper.selectMaterielByOrderId(orderVO.getId());
					if(OrderDetailVOList != null && OrderDetailVOList.size() > 0){
						orderVO.setOrderDetailList(OrderDetailVOList);
					}
				}
				taskOrderDetailVO.setDetailList(orderList);
			}
		}
		//根据车牌号查询车辆可用板位数
		TVehicleCustom tVehicleCustom = tVehicleCustomMapper.selectByPrimaryKey(taskOrderDetailVO.getVehicleId());
		//车辆板位数
		Byte carVolume = tVehicleCustom.getCarVolume() != null ? tVehicleCustom.getCarVolume() : 30;
		taskOrderDetailVO.setMaxTransportUnit(carVolume);
		
		return taskOrderDetailVO;
	}
	
	@Override
	public List<TaskListVO> listAllTaskAndOrder() throws Exception {
		return taskExtendMapper.listAllTaskAndOrder();
	}

	@Override
	public List<TaskScreenVO> listAllTaskOnScreen(TaskGirdQuery queryParam) throws Exception {
		String sortStr = queryParam.getSortStr();
		if(StringUtils.isBlank(sortStr)){
			queryParam.setSortStr("startTime ASC");
		}
		return taskExtendMapper.listAllTaskOnScreen(queryParam);
	}

	@Override
	@Transactional
	public void deleteTask(Long id) throws Exception {
		if(id == null || id <= 0){
            throw new RuntimeException("任务ID不能为空或者少于等于0！");
        }
		Date date = new Date();
		// 判断运输任务的确认状态：0未确认则可以删除1已确认则不可以删除
    	TTask data = tTaskMapper.selectByPrimaryKey(id);
    	if(data.getConfirmState() != null && data.getConfirmState() != 0)throw new BusinessException("任务已确认，删除失败!");
		//删除任务装卸货节点
		taskNodeExtendMapper.deleteTaskNoteExtendByTaskId(id);
		//删除任务节点对应的订单
		taskNodeExtendMapper.deleteNoteOrderByTaskId(id);
		//删除任务节点
		taskNodeExtendMapper.deleteNoteByTaskId(id);
		//将所关联的订单状态改为未调度（未生成）
		updateOrderGenerateStatus(id, 0, date);
		//删除任务与订单关联
    	taskExtendMapper.deleteTaskAndOrderByTaskId(id);
    	//查询该车辆的其他任务，并修改车辆的最早可用时间
    	List<TTask> list = taskExtendMapper.getVehicleTaskByVidAndTid(data.getId(), data.getVehicleId());
    	if(list!=null && !list.isEmpty()){
    		taskExtendMapper.UpdateVehicleCarvldTimeByVid(data.getId(), data.getVehicleId());
    	}else{
    		taskExtendMapper.UpdateVehicleCarvldTimeByVidAndDate(data.getVehicleId());
    	}
    	//删除任务
		taskExtendMapper.deleteTask(id);
		//添加日志
		insertLog(id, 3, date);
	}

	@Override
	public Map<String, Object> getListTaskNoAndPhone() throws Exception {
		return taskExtendMapper.getListTaskNoAndPhone();
	}

	@Override
	public List<Map<String, Object>> exportTaskAndOrderDetailGirdData(TaskGirdQuery queryParam) {
		String sortStr = "tUpdateTime, temp.taskNo, temp.same_pallet, temp.materielNo";
		queryParam.setSort(0);
		queryParam.setSortStr(sortStr);
		return taskExtendMapper.exportTaskAndOrderDetailGirdData(queryParam);
	}

	@Override
	public void updateActualStartByTaskId(Long taskId, Date date) {
		Map<String, Object> map = new HashMap<>();
		map.put("taskId", taskId);
		map.put("updateTime", date);
		taskExtendMapper.updateActualStartByTaskId(map);
	}
	
	@Override
	public void updateActualFinishByTaskId(Long taskId, Date date) {
		Map<String, Object> map = new HashMap<>();
		map.put("taskId", taskId);
		map.put("updateTime", date);
		taskExtendMapper.updateActualFinishByTaskId(map);
	}

	@Override
	public List<DriverWorkVO> driverGirdData(DriverGirdQuery queryParam) throws Exception {
		if(StringUtils.isBlank(queryParam.getSortStr())){
			queryParam.setSortStr("driverId DESC");
		}
		return taskExtendMapper.driverGirdData(queryParam);
	}

	@Override
	public List<TTask> getVehicleTaskByVidAndTid(Long taskId, Long vehicleId) {
		return taskExtendMapper.getVehicleTaskByVidAndTid(taskId, vehicleId);
	}
	@Override
	public void UpdateVehicleCarvldTimeByVid(Long taskId, Long vehicleId) {
		taskExtendMapper.UpdateVehicleCarvldTimeByVid(taskId, vehicleId);
	}

	@Override
	public void UpdateVehicleCarvldTimeByVidAndDate(Long vehicleId) {
		taskExtendMapper.UpdateVehicleCarvldTimeByVidAndDate(vehicleId);
	}

	@Override
	public void updateTaskRoutPallet(TTask task) throws Exception {
		taskExtendMapper.updateTaskRoutPallet(task);
	}
	public static void main(String[] args) {
		/*BigDecimal transportBoard = new BigDecimal(1.4834);
		BigDecimal transportBoard2 = new BigDecimal(10.225);
		BigDecimal transportBoard3 = new BigDecimal(0.999);
		transportBoard = transportBoard.add(transportBoard2);
		transportBoard = transportBoard.add(transportBoard3);
		System.out.println(transportBoard);*/
		
		 SimpleDateFormat HHMM = new SimpleDateFormat("HH:mm");
		 	Date date = new Date();
		  DateFormat df3 = DateFormat.getTimeInstance();//只显示出时分秒
		  String times = df3.format(date);
		  System.out.println(times);
		  System.out.println("s32580000:"+(17));
		  try {
			Date parse = HHMM.parse(times);
			System.out.println(parse.getTime());
			
			Date parse2 = HHMM.parse("17:09");
			System.out.println(parse2.getTime());
			Date parse3 = HHMM.parse("18:09");
			System.out.println(parse3.getTime() +":"+(36540000-32940000));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		  
		  DateFormat df4 = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL); //显示日期，周，上下午，时间（精确到秒）
		  System.out.println(df4.format(date));
		  DateFormat df5 = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG); //显示日期,上下午，时间（精确到秒）
		  System.out.println(df5.format(date));
		  DateFormat df6 = DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT); //显示日期，上下午,时间（精确到分）
		  System.out.println(df6.format(date));
		  DateFormat df7 = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.MEDIUM); //显示日期，时间（精确到分）
		System.out.println(df7.format(date));
		byte nodeNo = 1;
		nodeNo += ss();
		System.out.println(nodeNo);
	}
	public static byte ss(){
		byte nodeLen = 0;
		nodeLen ++;
		return nodeLen;
	}
	@Override
	public List<TTask> getNoDriverTask() {
		return taskExtendMapper.getNoDriverTask();
	}

	@Override
	public int automaticallyDrivers(List<TTask> taskList) throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
		//查询司机信息以及其最早可用时间、排班信息（上班下班时间）
		List<DriverTaskVO> driverList = taskExtendMapper.driverTaskAndShfit();
		int result = 0;
		for (int i = 0; i < taskList.size(); i++) {
			TTask tTask = taskList.get(i);
			for (DriverTaskVO driverTaskVO : driverList) {
				Date availableTime = driverTaskVO.getAvailableTime();//司机最早可用时间
				Date startTime = tTask.getStartTime();//当前任务的预计开始时间
				Double startTimeNums = (tTask.getStartTime() != null) ? TaskDispathDateUtils.parseCustomTime(sdf.format(tTask.getStartTime())) : null;
				boolean flag = compareWorkTime(driverTaskVO, startTimeNums);
				if(flag && (availableTime ==null || availableTime.getTime() < startTime.getTime())){
					result = updateTaskDriver(result, tTask, driverTaskVO);
					break;
                }
			}
			
		}
		return result;
	}

	private int updateTaskDriver(int result, TTask tTask, DriverTaskVO driverTaskVO) {
		//分配司机给任务
		tTask.setDriverId(driverTaskVO.getId());
		tTask.setDriverName(driverTaskVO.getDriverName());
		tTaskMapper.updateByPrimaryKeySelective(tTask);
		//修改此司机的最早可用时间为此任务的预计完成时间
		driverTaskVO.setAvailableTime(tTask.getFinishTime());
		//任务分配成功记录+1
		result++;
		return result;
	}

	private boolean compareWorkTime(DriverTaskVO driverTaskVO, Double startTimeNums) {
		boolean flag = false;
		Double driverBeginTimeNums = TaskDispathDateUtils.parseCustomTime(driverTaskVO.getWorkStartTime());
		Double driverEndTimeNums = TaskDispathDateUtils.parseCustomTime(driverTaskVO.getWorkEndTime());
		//如果当前司机排班信息是跨天的，就把司机上班时间减12小时把下班时间加12小时等于把跨天的时间段整成同一天的时间
		if(driverBeginTimeNums > driverEndTimeNums){//跨天的
		    driverBeginTimeNums -= 0.5d;
		    driverEndTimeNums += 0.5d;
		    //如果任务开始时间是比跨天的司机上班时间早,代表这个时间已经是第二天的时间范围所以要加上12小时.
		    //反之如果时间比司机上班司机晚证明时间还在当天内,就减12小时
		    startTimeNums = (startTimeNums < driverBeginTimeNums) ? startTimeNums + 0.5d : startTimeNums - 0.5d;
		}
		//判断当前任务预计开始时间是否离当前司机下班时间一个小时之内，如果是就把当前任务分配给当前车辆下一个班次的司机
		Double difVal = driverEndTimeNums - startTimeNums;
		//任务的预计开始时间要大于司机的上班时间
		Double startVal = startTimeNums - driverBeginTimeNums;
		if(difVal > 0 && difVal >= 0.041666666666666664 && startVal >= 0) flag = true;
		return flag;
	}
	
}
